home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-ppc-src / pasm / tables.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  10KB  |  345 lines

  1. /* $VER: pasm tables.c V1.2 (24.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (24.10.98) phx
  16.  *        An empty section with reloc symbols will no longer be deleted.
  17.  * v0.8   (14.02.98) phx
  18.  *        Alignment list for each section. This fixes the problems
  19.  *        with optimizations.
  20.  * v0.7   (01.01.98) phx
  21.  *        search_instr() is global.
  22.  * v0.5   (08.10.97) phx
  23.  *        .globl directive declares unknown symbols in pass 1 as
  24.  *        externally defined. If the symbol is defined later in the
  25.  *        source, it will be made global by add_symbol().
  26.  * v0.3   (05.04.97) phx
  27.  *        Minor changes.
  28.  * v0.2   (25.03.97) phx
  29.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  30.  *        or ELF output format may be selected. ELF is default for all
  31.  *        currently supported platforms. PPCasm supports nine different
  32.  *        relocation types (there are much more...).
  33.  *        Compiles and works also under NetBSD/amiga (68k).
  34.  *        Changed function declaration to 'new style' in all sources
  35.  *        (to avoid problems with '...' for example).
  36.  *        Externally defined symbols will automatically get global binding.
  37.  * v0.1   (11.03.97) phx
  38.  *        First test version with all PowerPC instructions and most
  39.  *        important directives. Only raw, absolute output.
  40.  * v0.0   (22.02.97) phx
  41.  *        File created.
  42.  */
  43.  
  44.  
  45. #define TABLES_C
  46. #include "ppcasm.h"
  47.  
  48.  
  49. void init_hashtables(struct GlobalVars *);
  50. void add_macro(struct GlobalVars *,struct Macro *);
  51. struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
  52. unsigned long elf_hash(unsigned char *);
  53. struct Symbol *search_symbol(struct GlobalVars *,char *);
  54. struct CPUInstr *search_instr(struct GlobalVars *,char *);
  55. struct Section *search_section(struct GlobalVars *,char *);
  56. void search_opcode(struct GlobalVars *,struct ParsedLine *,char *,char *);
  57.  
  58. static void *alloc_hashtable(size_t);
  59. static void add_instruction(struct GlobalVars *,struct CPUInstr *);
  60. static void add_directive(struct GlobalVars *,struct Directive *);
  61. static struct Directive *search_directive(struct GlobalVars *,char *);
  62. static struct Macro *search_macro(struct GlobalVars *,char *);
  63. static void execute_macro(struct GlobalVars *,struct ParsedLine *);
  64. static void execute_directive(struct GlobalVars *,struct ParsedLine *);
  65.  
  66.  
  67.  
  68. void init_hashtables(struct GlobalVars *gv)
  69. {
  70.   struct CPUInstr *ins = instructions;
  71.   struct Directive *dir = directives;
  72.  
  73.   gv->symbols = alloc_hashtable(SYMHTABSIZE);
  74.   gv->instr = alloc_hashtable(INSTRHTABSIZE);
  75.   gv->directives = alloc_hashtable(DIRHTABSIZE);
  76.   gv->macros = alloc_hashtable(MACROHTABSIZE);
  77.   while (ins->name)
  78.     add_instruction(gv,ins++);
  79.   while (dir->name)
  80.     add_directive(gv,dir++);
  81. }
  82.  
  83.  
  84. static void *alloc_hashtable(size_t entries)
  85. {
  86.   return (alloczero(entries * sizeof(void *)));
  87. }
  88.  
  89.  
  90. static void add_instruction(struct GlobalVars *gv,struct CPUInstr *ins)
  91. /* make new entry into instruction hash table */
  92. {
  93.   struct CPUInstr *chain;
  94.   unsigned long offs = elf_hash(ins->name)%INSTRHTABSIZE;
  95.  
  96.   if (!(ins->flags & F_EXTENDED) || !gv->noextmnemo) {
  97.     if (chain = gv->instr[offs])
  98.       ins->hash_chain = chain;
  99.     else
  100.       ins->hash_chain = NULL;
  101.     gv->instr[offs] = ins;
  102.   }
  103. }
  104.  
  105.  
  106. static void add_directive(struct GlobalVars *gv,struct Directive *dir)
  107. /* make new entry into directive hash table */
  108. {
  109.   struct Directive *chain;
  110.   unsigned long offs = elf_hash(dir->name)%DIRHTABSIZE;
  111.  
  112.   if (chain = gv->directives[offs])
  113.     dir->hash_chain = chain;
  114.   else
  115.     dir->hash_chain = NULL;
  116.   gv->directives[offs] = dir;
  117. }
  118.  
  119.  
  120. void add_macro(struct GlobalVars *gv,struct Macro *mac)
  121. /* make new entry into macro hash table */
  122. {
  123.   struct Macro *chain,*m;
  124.   unsigned long offs = elf_hash(mac->name)%MACROHTABSIZE;
  125.  
  126.   if (chain = m = gv->macros[offs]) {  /* hash code already used? */
  127.     do {
  128.       if (!strcmp(m->name,mac->name)) {
  129.         error(8,mac->name);  /* macro defined twice! */
  130.         break;
  131.       }
  132.     }
  133.     while (m = m->hash_chain);
  134.   }
  135.   gv->macros[offs] = mac;
  136.   mac->hash_chain = chain;
  137. }
  138.  
  139.  
  140. struct Symbol *add_symbol(struct GlobalVars *gv,char *name,uint8 type,
  141.                           uint32 value)
  142. /* define new symbol - absolute, relocatable or external */
  143. {
  144.   struct Symbol *sym,*chain;
  145.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  146.  
  147.   if (chain = sym = gv->symbols[offs]) {  /* hash code already used? */
  148.     do {
  149.       if (!strcmp(name,sym->name)) {
  150.         if (sym->type == SYM_EXTERN) { /* declared ext. visible by .globl? */
  151.           if ((sym->type = type) == SYM_RELOC) {
  152.             struct Section *cs = gv->csect;
  153.             sym->relsect = cs;
  154.             cs->flags |= SF_HASSYMS;
  155.             sym->alignpoint = cs->current_align;
  156.           }
  157.           sym->value = value;
  158.         }
  159.         else
  160.           error(7,name);  /* symbol defined twice! */
  161.         return (sym);
  162.       }
  163.     }
  164.     while (sym = sym->hash_chain);
  165.   }
  166.   gv->symbols[offs] = sym = alloczero(sizeof(struct Symbol));
  167.   sym->hash_chain = chain;
  168.   sym->name = allocstring(name);
  169.   sym->value = value;
  170.   if ((sym->type = type) == SYM_RELOC) {
  171.     sym->relsect = gv->csect;
  172.     sym->alignpoint = gv->csect->current_align;
  173.   }
  174.   else if (type == SYM_EXTERN) {
  175.     sym->bind = SYMB_GLOBAL;
  176.     if (sym->type==SYM_RELOC)
  177.       sym->relsect->flags |= SF_HASSYMS;
  178.   }
  179.   return (sym);
  180. }
  181.  
  182.  
  183. unsigned long elf_hash(unsigned char *name)
  184. /* calculate a hash code as used in ELF objects */
  185. {
  186.   unsigned long h=0,g;
  187.  
  188.   while (*name) {
  189.     h = (h << 4) + *name++;
  190.     if (g = h & 0xf0000000)
  191.       h ^= g >> 24;
  192.     h &= ~g;
  193.   }
  194.   return (h);
  195. }
  196.  
  197.  
  198. struct Symbol *search_symbol(struct GlobalVars *gv,char *name)
  199. /* find a symbol in the symbol hash table */
  200. {
  201.   struct Symbol *chain;
  202.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  203.  
  204.   chain = gv->symbols[offs];
  205.   while (chain) {
  206.     if (!strcmp(chain->name,name))
  207.       return (chain);
  208.     chain = chain->hash_chain;
  209.   }
  210.   return (NULL);
  211. }
  212.  
  213.  
  214. struct CPUInstr *search_instr(struct GlobalVars *gv,char *name)
  215. /* find an instruction in the instruction hash table */
  216. {
  217.   struct CPUInstr *chain;
  218.   unsigned long offs = elf_hash(name)%INSTRHTABSIZE;
  219.  
  220.   chain = gv->instr[offs];
  221.   while (chain) {
  222.     if (!strcmp(chain->name,name))
  223.       return (chain);
  224.     chain = chain->hash_chain;
  225.   }
  226.   return (NULL);
  227. }
  228.  
  229.  
  230. static struct Directive *search_directive(struct GlobalVars *gv,char *name)
  231. /* find a directive in the directive hash table */
  232. {
  233.   struct Directive *chain;
  234.   unsigned long offs = elf_hash(name)%DIRHTABSIZE;
  235.  
  236.   chain = gv->directives[offs];
  237.   while (chain) {
  238.     if (!strcmp(chain->name,name))
  239.       return (chain);
  240.     chain = chain->hash_chain;
  241.   }
  242.   return (NULL);
  243. }
  244.  
  245.  
  246. static struct Macro *search_macro(struct GlobalVars *gv,char *name)
  247. /* find a macro in the macro hash table */
  248. {
  249.   struct Macro *chain;
  250.   unsigned long offs = elf_hash(name)%MACROHTABSIZE;
  251.  
  252.   chain = gv->macros[offs];
  253.   while (chain) {
  254.     if (!strcmp(chain->name,name))
  255.       return (chain);
  256.     chain = chain->hash_chain;
  257.   }
  258.   return (NULL);
  259. }
  260.  
  261.  
  262. struct Section *search_section(struct GlobalVars *gv,char *name)
  263. {
  264.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  265.  
  266.   while (nextsec = (struct Section *)sec->n.next) {
  267.     if (!strcmp(name,sec->name))
  268.       return (sec);
  269.     sec = nextsec;
  270.   }
  271.   return (NULL);
  272. }
  273.  
  274.  
  275. void search_opcode(struct GlobalVars *gv,struct ParsedLine *pl,
  276.                    char *opname,char *operand)
  277. {
  278.   if (gv->alignflag)
  279.     pl->flags |= PLF_ALIGN;
  280.   gv->alignflag = FALSE;
  281.   if (pl->opcode = (void *)search_macro(gv,opname)) {
  282.     pl->type = OT_MACRO;
  283.     pl->operand = operand;
  284.     execute_macro(gv,pl);
  285.   }
  286.   else if (pl->opcode = (void *)search_instr(gv,opname)) {
  287.     pl->type = OT_INSTRUCTION;
  288.     pl->operand = allocstring(operand);
  289.     gv->csect->pc += 4;  /* every PPC instruction has a size of 4 bytes */
  290.   }
  291.   else if (pl->opcode = (void *)search_directive(gv,opname)) {
  292.     pl->type = OT_DIRECTIVE;
  293.     pl->operand = allocstring(operand);
  294.     execute_directive(gv,pl);
  295.   }
  296.   else if (pl->opcode = (void *)search_section(gv,opname)) {
  297.     pl->type = OT_SECTION;
  298.     activate_section(gv,(struct Section *)pl->opcode);
  299.   }
  300.   else
  301.     error(10,opname);  /* Unknown opcode */
  302. }
  303.  
  304.  
  305. static void execute_macro(struct GlobalVars *gv,struct ParsedLine *pl)
  306. /* creates a SourceText structure for every macro invocation, parses */
  307. /* macro parameters and recursively calls pass1() to execute the macro */
  308. {
  309.   struct Macro *m = (struct Macro *)pl->opcode;
  310.   struct MacroParams *mp = alloczero(sizeof(struct MacroParams));
  311.   struct SourceText *stxt = alloc(sizeof(struct SourceText));
  312.   char *mac_params = alloc(strlen(pl->operand)+1);
  313.   uint32 oldnarg = gv->nargsym->value;
  314.  
  315.   /* create SourceText node for macro-call */
  316.   stxt->name = m->name;
  317.   stxt->text = m->text;
  318.   stxt->nlines = m->nlines;
  319.   stxt->plin = alloczero(m->nlines * sizeof(struct ParsedLine));
  320.   addtail(&gv->sourcelist,&stxt->n);
  321.  
  322.   /* initialize MacroParams structure */
  323.   mp->call_id = gv->macrocnt++;
  324.   strcpy(mac_params,pl->operand);
  325.   read_macro_params(gv,pl,mp,mac_params);
  326.   pl->narg = (uint8)mp->narg;
  327.   gv->nargsym->value = mp->narg;
  328.  
  329.   /* recursively call pass 1 and create new SourceThread */
  330.   pass1(gv,stxt,mp,gv->cthread);
  331.   gv->nargsym->value = oldnarg;
  332.  
  333.   /* cleanup */
  334.   free(mp);
  335.   pl->opcode = stxt;
  336. }
  337.  
  338.  
  339. static void execute_directive(struct GlobalVars *gv,struct ParsedLine *pl)
  340. {
  341.   struct Directive *d = (struct Directive *)pl->opcode;
  342.  
  343.   (d->dfunct)(gv,pl);
  344. }
  345.